package com.hzy.fivepalace.admin.service;

import com.hzy.fivepalace.admin.controller.base.BaseController;
import com.hzy.fivepalace.admin.dao.AdminLoginInfo;
import com.hzy.fivepalace.admin.dao.AdminToken;
import com.hzy.fivepalace.common.util.IpUtil;
import com.hzy.fivepalace.common.util.ResponseUtil;
import com.hzy.fivepalace.common.util.bcrypt.BCryptPasswordEncoder;
import com.hzy.fivepalace.db.domain.DtsAdmin;
import com.hzy.fivepalace.db.service.DtsAdminService;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 登录鉴权服务
 */
@Service
public class LoginService extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(LoginService.class);

    @Autowired
    private DtsAdminService adminService;

    @Autowired
    private AdminTokenManager userTokenManager;

    @Resource
    private Redisson redisson;


    /**
     * 登录
     *
     * @param loginInfo
     * @param request
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public Object toLogin(AdminLoginInfo loginInfo, HttpServletRequest request) {
        if (StringUtils.isBlank(loginInfo.getUsername())) {
            return ResponseUtil.fail("请输入账号");
        }
        RLock lock = redisson.getLock("admin_login_" + loginInfo.getUsername());
        if (lock.isLocked()) {
            return ResponseUtil.frequent();
        }
        lock.lock(30, TimeUnit.SECONDS);

        if (StringUtils.isBlank(loginInfo.getPassword())) {
            lock.unlock();
            return ResponseUtil.fail("请输入密码");
        }
        DtsAdmin admin = adminService.findAdmin(loginInfo.getUsername());
        if (null == admin) {
            lock.unlock();
            return ResponseUtil.fail("账号或密码错误");
        }
        //密码比对
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(loginInfo.getPassword(), admin.getPassword())) {
            lock.unlock();
            return ResponseUtil.fail("账号或密码错误");
        }

        //判断账号是否被删除
        if (admin.getDeleted()) {
            lock.unlock();
            return ResponseUtil.fail("该账号已被删除");
        }

        Map<Object, Object> result = new HashMap<Object, Object>();
        // token
        AdminToken userToken = null;
        try {
            //生成新token
            userToken = userTokenManager.generateToken(admin.getId(), request.getSession().getId());
        } catch (Exception e) {
            logger.error("微信登录失败,生成token失败：userId:{},msg:{}", admin.getId(), e.getMessage());
            lock.unlock();
            return ResponseUtil.fail("token生成失败");
        }
        result.put("token", userToken.getToken());
        result.put("nickName", admin.getUsername());
        result.put("avatar", admin.getAvatar());
        //记录用户登录信息
        admin.setLastLoginTime(LocalDateTime.now());
        admin.setLastLoginIp(IpUtil.getRealIp(request));
        admin.setUpdateTime(LocalDateTime.now());
        adminService.updateById(admin);
        lock.unlock();
        return ResponseUtil.ok("登录成功", result);
    }



    /**
     * 退出登录
     *
     * @param userId
     * @return
     */
    public Object toLogout(Integer userId) {
        RLock lock = redisson.getLock("admin_toLogout_" + userId);
        if (lock.isLocked()) {
            return ResponseUtil.frequent();
        }
        lock.lock(30, TimeUnit.SECONDS);
        try {
            userTokenManager.removeToken(getAdminToken());
        } catch (Exception e) {
            logger.error("退出登录出错：userId:{},msg:{}", userId, e.getMessage());
            lock.unlock();
            return ResponseUtil.fail("退出登录异常");
        }
        //移除锁
        lock.unlock();
        return ResponseUtil.ok("退出成功", null);
    }

}
